// 娑堟伅澶�
package com.packet;

import java.nio.ByteBuffer;

import com.databus.*;
import com.tool.Utilities;

public class PackageHeader {
	
	public static int MAX_SINGLE_PACKAGE_SIZE = 2*1024 * 1024;           //2M
	public static int MAX_TOTAL_PACKAGE = 128;                         //

	public static class MsgType {
		public static final byte Request  = (byte) 1;   //
		public static final byte Response = (byte) 2;   //
		public static final byte Publish  = (byte) 3;   //
	};
	public static final int SIZE_OF_HEAD = 44;
	
	
	public static final byte flag1 = 94;        //
	public static final byte flag2 = 94;        //
	public byte crc;         //
	public byte version=1;     //
	public byte type = MsgType.Request;        //
	public byte offset = SIZE_OF_HEAD;     //

	public short options;                                //

	public short codeinfo;                               //

	public short multipageinfo;                          //
	public int serialnum;                               //
	public int bodysize;                                //
	public int srcaddr;                                 //
	public int dstaddr;                                 //
	public int command;                                 //
	public short code;
	public short other;
	// 璁剧疆Option
	// multicast : 鏄惁缁勬挱
	// sequence  : 鏄惁鏃跺簭
	public void SetOption(Boolean ext, Boolean multicast, Boolean sequence)
	{
		SetOption(ext,false, (byte)0, multicast, sequence, (byte)0, false);
	}
	
	public void SetOption(Boolean ext,Boolean needreply, byte protocol, Boolean multicast, Boolean sequence,  byte loadbalance, Boolean ispriority)
	{
		options =  (short)((ext ? 0x1 : 0x0) | (needreply ? 0x2 : 0x0) | (protocol << 2 & 0x0C) | (multicast ? 0x10 : 0x0) | (sequence ? 0x20 : 0x0) | (loadbalance << 6 & 0xC0) | (ispriority ? 0x100 : 0x0) ) ;
	}

	public void SetProtocol(short protocol)
	{
		options |=((protocol & 0x03) << 2);
	}

	public short GetProtocol()
	{
		return (short)((options >> 2) & 0x03);
	}
	// 鏄惁鏈夋墿灞曚俊鎭�
	public boolean IsExt()
	{
		return 0 != (options & 0x1);
	}
	
	// 鏄惁涓烘椂搴忔秷鎭�
	public boolean IsSequence()
	{
		return 0 != (options & 0x20);
	}
	
	// 鏄惁涓烘櫘閫氶�氱煡娑堟伅
	public boolean IsPubMsg()
	{
		return (type == MsgType.Publish);
	}
	
	// 璁剧疆缂栫爜淇℃伅
	// iszip : 鏄惁鍘嬬缉
	// isencrypt : 鏄惁鍔犲瘑
	// compratio : 鍘嬬缉姣�
	public void SetCodeInfo(Boolean iszip, Boolean isencrypt, short compratio)
	{
		codeinfo = (short)((isencrypt ? 0x1 : 0x0) | (iszip ? 0x2 : 0x0) |  (compratio << 6 & 0xFFFF));
	}
	
	// 鏄惁鍘嬬缉
	public Boolean IsZip() 
	{
		return 0 != (codeinfo & 0x2);
	}

	public boolean isMulti() 
	{
		return 0 != (multipageinfo & 0x1);
	}

	public short getMultiPageNo() 
	{
		return (short)(multipageinfo >> 1);
	}

	public void setMulti(int pageNo) 
	{
		multipageinfo = (short) (0x1 | (pageNo << 1));
	}

	// 鍙嶅簭鍒楀寲娑堟伅澶�
	public void unserialize(byte[] headers) 
	{
		if(headers.length < SIZE_OF_HEAD - 2)
		{
			Log.error("Message Header Size Is Error, size = " + headers.length);
			bodysize = -1;
			return;
		}
		ByteBuffer buffer = ByteBuffer.wrap(headers);
		crc = buffer.get();
		
		byte sum=0;
		for(int i=1;i<headers.length;i++)
			sum+=headers[i];
		if(sum!=crc)
		{
			Log.error("Message Header crc Error, size = " + headers.length);
			bodysize = -1;
			return;
		}
		
		version = buffer.get();
		type = buffer.get();
		offset = buffer.get();
		options = buffer.getShort();
		codeinfo = buffer.getShort();
		multipageinfo = buffer.getShort();
		serialnum = buffer.getInt();
		bodysize = buffer.getInt();
		srcaddr = buffer.getInt();
		dstaddr = buffer.getInt();
		command = buffer.getInt();
		code = buffer.getShort();
		other = buffer.getShort();
		
	}
	
	// 搴忓垪鍖栨秷鎭ご
	public byte[] serialize() 
	{
		ByteBuffer buffer = ByteBuffer.allocate(SIZE_OF_HEAD);
		
		buffer.put(flag1);
		buffer.put(flag2);
		buffer.put(crc);
		buffer.put(version);
		buffer.put(type);
		buffer.put(offset);
		buffer.put(Utilities.short2Bytes(options));
		buffer.put(Utilities.short2Bytes(codeinfo));
		buffer.put(Utilities.short2Bytes(multipageinfo));
		buffer.put(Utilities.int2Bytes(serialnum));
		buffer.put(Utilities.int2Bytes(bodysize));
		buffer.put(Utilities.int2Bytes(srcaddr));
		buffer.put(Utilities.int2Bytes(dstaddr));
		buffer.put(Utilities.int2Bytes(command));
		buffer.put(Utilities.short2Bytes(code));
		buffer.put(Utilities.short2Bytes(other));
	
		crc=0;
		byte[] bytes=buffer.array();
		for(int i=3;i<bytes.length;i++)
			crc+=bytes[i];
		bytes[2]=crc;
		return bytes;
	}	
}
